home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Python / thread_pthread.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-03  |  10.4 KB  |  414 lines

  1. /* Posix threads interface */
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <pthread.h>
  6.  
  7.  
  8. /* try to determine what version of the Pthread Standard is installed.
  9.  * this is important, since all sorts of parameter types changed from
  10.  * draft to draft and there are several (incompatible) drafts in
  11.  * common use.  these macros are a start, at least. 
  12.  * 12 May 1997 -- david arnold <davida@pobox.com>
  13.  */
  14.  
  15. #if defined(__ultrix) && defined(__mips) && defined(_DECTHREADS_)
  16. /* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
  17. #  define PY_PTHREAD_D4
  18.  
  19. #elif defined(__osf__) && defined (__alpha)
  20. /* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
  21. #  if !defined(_PTHREAD_ENV_ALPHA) || defined(_PTHREAD_USE_D4) || defined(PTHREAD_USE_D4)
  22. #    define PY_PTHREAD_D4
  23. #  else
  24. #    define PY_PTHREAD_STD
  25. #  endif
  26.  
  27. #elif defined(_AIX)
  28. /* SCHED_BG_NP is defined if using AIX DCE pthreads
  29.  * but it is unsupported by AIX 4 pthreads. Default
  30.  * attributes for AIX 4 pthreads equal to NULL. For
  31.  * AIX DCE pthreads they should be left unchanged.
  32.  */
  33. #  if !defined(SCHED_BG_NP)
  34. #    define PY_PTHREAD_STD
  35. #  else
  36. #    define PY_PTHREAD_D7
  37. #  endif
  38.  
  39. #elif defined(__DGUX)
  40. #  define PY_PTHREAD_D6
  41.  
  42. #elif defined(__hpux) && defined(_DECTHREADS_)
  43. #  define PY_PTHREAD_D4
  44.  
  45. #else /* Default case */
  46. #  define PY_PTHREAD_STD
  47.  
  48. #endif
  49.  
  50.  
  51. /* set default attribute object for different versions */
  52.  
  53. #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
  54. #  define pthread_attr_default pthread_attr_default
  55. #  define pthread_mutexattr_default pthread_mutexattr_default
  56. #  define pthread_condattr_default pthread_condattr_default
  57. #elif defined(PY_PTHREAD_STD) || defined(PY_PTHREAD_D6)
  58. #  define pthread_attr_default ((pthread_attr_t *)NULL)
  59. #  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
  60. #  define pthread_condattr_default ((pthread_condattr_t *)NULL)
  61. #endif
  62.  
  63.  
  64. /* A pthread mutex isn't sufficient to model the Python lock type
  65.  * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
  66.  * following are undefined:
  67.  *  -> a thread tries to lock a mutex it already has locked
  68.  *  -> a thread tries to unlock a mutex locked by a different thread
  69.  * pthread mutexes are designed for serializing threads over short pieces
  70.  * of code anyway, so wouldn't be an appropriate implementation of
  71.  * Python's locks regardless.
  72.  *
  73.  * The pthread_lock struct implements a Python lock as a "locked?" bit
  74.  * and a <condition, mutex> pair.  In general, if the bit can be acquired
  75.  * instantly, it is, else the pair is used to block the thread until the
  76.  * bit is cleared.     9 May 1994 tim@ksr.com
  77.  */
  78.  
  79. typedef struct {
  80.     char             locked; /* 0=unlocked, 1=locked */
  81.     /* a <cond, mutex> pair to handle an acquire of a locked lock */
  82.     pthread_cond_t   lock_released;
  83.     pthread_mutex_t  mut;
  84. } pthread_lock;
  85.  
  86. #define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
  87.  
  88. /*
  89.  * Initialization.
  90.  */
  91.  
  92. #ifdef _HAVE_BSDI
  93. static void _noop()
  94. {
  95. }
  96.  
  97. static void PyThread__init_thread _P0()
  98. {
  99.     /* DO AN INIT BY STARTING THE THREAD */
  100.     static int dummy = 0;
  101.     pthread_t thread1;
  102.     pthread_create(&thread1, NULL, (void *) _noop, &dummy);
  103.     pthread_join(thread1, NULL);
  104. }
  105.  
  106. #else /* !_HAVE_BSDI */
  107.  
  108. static void PyThread__init_thread _P0()
  109. {
  110. #if defined(_AIX) && defined(__GNUC__)
  111.     pthread_init();
  112. #endif
  113. }
  114.  
  115. #endif /* !_HAVE_BSDI */
  116.  
  117. /*
  118.  * Thread support.
  119.  */
  120.  
  121.  
  122. int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
  123. {
  124.     pthread_t th;
  125.     int success;
  126.     dprintf(("PyThread_start_new_thread called\n"));
  127.     if (!initialized)
  128.         PyThread_init_thread();
  129.  
  130.     success = pthread_create(&th, 
  131. #if defined(PY_PTHREAD_D4)
  132.                  pthread_attr_default,
  133.                  (pthread_startroutine_t)func, 
  134.                  (pthread_addr_t)arg
  135. #elif defined(PY_PTHREAD_D6)
  136.                  pthread_attr_default,
  137.                  (void* (*)_P((void *)))func,
  138.                  arg
  139. #elif defined(PY_PTHREAD_D7)
  140.                  pthread_attr_default,
  141.                  func,
  142.                  arg
  143. #elif defined(PY_PTHREAD_STD)
  144.                  (pthread_attr_t*)NULL,
  145.                  (void* (*)_P((void *)))func,
  146.                  (void *)arg
  147. #endif
  148.                  );
  149.  
  150.     if (success == 0) {
  151. #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
  152.         pthread_detach(&th);
  153. #elif defined(PY_PTHREAD_STD)
  154.         pthread_detach(th);
  155. #endif
  156.     }
  157.     return success != 0 ? 0 : 1;
  158. }
  159.  
  160. long PyThread_get_thread_ident _P0()
  161. {
  162.     volatile pthread_t threadid;
  163.     if (!initialized)
  164.         PyThread_init_thread();
  165.     /* Jump through some hoops for Alpha OSF/1 */
  166.     threadid = pthread_self();
  167.     return (long) *(long *) &threadid;
  168. }
  169.  
  170. static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup)
  171. {
  172.     dprintf(("PyThread_exit_thread called\n"));
  173.     if (!initialized) {
  174.         if (no_cleanup)
  175.             _exit(0);
  176.         else
  177.             exit(0);
  178.     }
  179. }
  180.  
  181. void PyThread_exit_thread _P0()
  182. {
  183.     do_PyThread_exit_thread(0);
  184. }
  185.  
  186. void PyThread__exit_thread _P0()
  187. {
  188.     do_PyThread_exit_thread(1);
  189. }
  190.  
  191. #ifndef NO_EXIT_PROG
  192. static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
  193. {
  194.     dprintf(("PyThread_exit_prog(%d) called\n", status));
  195.     if (!initialized)
  196.         if (no_cleanup)
  197.             _exit(status);
  198.         else
  199.             exit(status);
  200. }
  201.  
  202. void PyThread_exit_prog _P1(status, int status)
  203. {
  204.     do_PyThread_exit_prog(status, 0);
  205. }
  206.  
  207. void PyThread__exit_prog _P1(status, int status)
  208. {
  209.     do_PyThread_exit_prog(status, 1);
  210. }
  211. #endif /* NO_EXIT_PROG */
  212.  
  213. /*
  214.  * Lock support.
  215.  */
  216. PyThread_type_lock PyThread_allocate_lock _P0()
  217. {
  218.     pthread_lock *lock;
  219.     int status, error = 0;
  220.  
  221.     dprintf(("PyThread_allocate_lock called\n"));
  222.     if (!initialized)
  223.         PyThread_init_thread();
  224.  
  225.     lock = (pthread_lock *) malloc(sizeof(pthread_lock));
  226.     memset((void *)lock, '\0', sizeof(pthread_lock));
  227.     if (lock) {
  228.         lock->locked = 0;
  229.  
  230.         status = pthread_mutex_init(&lock->mut,
  231.                         pthread_mutexattr_default);
  232.         CHECK_STATUS("pthread_mutex_init");
  233.  
  234.         status = pthread_cond_init(&lock->lock_released,
  235.                        pthread_condattr_default);
  236.         CHECK_STATUS("pthread_cond_init");
  237.  
  238.         if (error) {
  239.             free((void *)lock);
  240.             lock = 0;
  241.         }
  242.     }
  243.  
  244.     dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock));
  245.     return (PyThread_type_lock) lock;
  246. }
  247.  
  248. void PyThread_free_lock _P1(lock, PyThread_type_lock lock)
  249. {
  250.     pthread_lock *thelock = (pthread_lock *)lock;
  251.     int status, error = 0;
  252.  
  253.     dprintf(("PyThread_free_lock(%lx) called\n", (long)lock));
  254.  
  255.     status = pthread_mutex_destroy( &thelock->mut );
  256.     CHECK_STATUS("pthread_mutex_destroy");
  257.  
  258.     status = pthread_cond_destroy( &thelock->lock_released );
  259.     CHECK_STATUS("pthread_cond_destroy");
  260.  
  261.     free((void *)thelock);
  262. }
  263.  
  264. int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag)
  265. {
  266.     int success;
  267.     pthread_lock *thelock = (pthread_lock *)lock;
  268.     int status, error = 0;
  269.  
  270.     dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
  271.  
  272.     status = pthread_mutex_lock( &thelock->mut );
  273.     CHECK_STATUS("pthread_mutex_lock[1]");
  274.     success = thelock->locked == 0;
  275.     if (success) thelock->locked = 1;
  276.     status = pthread_mutex_unlock( &thelock->mut );
  277.     CHECK_STATUS("pthread_mutex_unlock[1]");
  278.  
  279.     if ( !success && waitflag ) {
  280.         /* continue trying until we get the lock */
  281.  
  282.         /* mut must be locked by me -- part of the condition
  283.          * protocol */
  284.         status = pthread_mutex_lock( &thelock->mut );
  285.         CHECK_STATUS("pthread_mutex_lock[2]");
  286.         while ( thelock->locked ) {
  287.             status = pthread_cond_wait(&thelock->lock_released,
  288.                            &thelock->mut);
  289.             CHECK_STATUS("pthread_cond_wait");
  290.         }
  291.         thelock->locked = 1;
  292.         status = pthread_mutex_unlock( &thelock->mut );
  293.         CHECK_STATUS("pthread_mutex_unlock[2]");
  294.         success = 1;
  295.     }
  296.     if (error) success = 0;
  297.     dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
  298.     return success;
  299. }
  300.  
  301. void PyThread_release_lock _P1(lock, PyThread_type_lock lock)
  302. {
  303.     pthread_lock *thelock = (pthread_lock *)lock;
  304.     int status, error = 0;
  305.  
  306.     dprintf(("PyThread_release_lock(%lx) called\n", (long)lock));
  307.  
  308.     status = pthread_mutex_lock( &thelock->mut );
  309.     CHECK_STATUS("pthread_mutex_lock[3]");
  310.  
  311.     thelock->locked = 0;
  312.  
  313.     status = pthread_mutex_unlock( &thelock->mut );
  314.     CHECK_STATUS("pthread_mutex_unlock[3]");
  315.  
  316.     /* wake up someone (anyone, if any) waiting on the lock */
  317.     status = pthread_cond_signal( &thelock->lock_released );
  318.     CHECK_STATUS("pthread_cond_signal");
  319. }
  320.  
  321. /*
  322.  * Semaphore support.
  323.  */
  324.  
  325. struct semaphore {
  326.     pthread_mutex_t mutex;
  327.     pthread_cond_t cond;
  328.     int value;
  329. };
  330.  
  331. PyThread_type_sema PyThread_allocate_sema _P1(value, int value)
  332. {
  333.     struct semaphore *sema;
  334.     int status, error = 0;
  335.  
  336.     dprintf(("PyThread_allocate_sema called\n"));
  337.     if (!initialized)
  338.         PyThread_init_thread();
  339.  
  340.     sema = (struct semaphore *) malloc(sizeof(struct semaphore));
  341.     if (sema != NULL) {
  342.         sema->value = value;
  343.         status = pthread_mutex_init(&sema->mutex,
  344.                         pthread_mutexattr_default);
  345.         CHECK_STATUS("pthread_mutex_init");
  346.         status = pthread_cond_init(&sema->cond,
  347.                        pthread_condattr_default);
  348.         CHECK_STATUS("pthread_cond_init");
  349.         if (error) {
  350.             free((void *) sema);
  351.             sema = NULL;
  352.         }
  353.     }
  354.     dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema));
  355.     return (PyThread_type_sema) sema;
  356. }
  357.  
  358. void PyThread_free_sema _P1(sema, PyThread_type_sema sema)
  359. {
  360.     int status, error = 0;
  361.     struct semaphore *thesema = (struct semaphore *) sema;
  362.  
  363.     dprintf(("PyThread_free_sema(%lx) called\n", (long) sema));
  364.     status = pthread_cond_destroy(&thesema->cond);
  365.     CHECK_STATUS("pthread_cond_destroy");
  366.     status = pthread_mutex_destroy(&thesema->mutex);
  367.     CHECK_STATUS("pthread_mutex_destroy");
  368.     free((void *) thesema);
  369. }
  370.  
  371. int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag)
  372. {
  373.     int status, error = 0, success;
  374.     struct semaphore *thesema = (struct semaphore *) sema;
  375.  
  376.     dprintf(("PyThread_down_sema(%lx, %d) called\n", (long) sema, waitflag));
  377.     status = pthread_mutex_lock(&thesema->mutex);
  378.     CHECK_STATUS("pthread_mutex_lock");
  379.     if (waitflag) {
  380.         while (!error && thesema->value <= 0) {
  381.             status = pthread_cond_wait(&thesema->cond,
  382.                            &thesema->mutex);
  383.             CHECK_STATUS("pthread_cond_wait");
  384.         }
  385.     }
  386.     if (error)
  387.         success = 0;
  388.     else if (thesema->value > 0) {
  389.         thesema->value--;
  390.         success = 1;
  391.     }
  392.     else
  393.         success = 0;
  394.     status = pthread_mutex_unlock(&thesema->mutex);
  395.     CHECK_STATUS("pthread_mutex_unlock");
  396.     dprintf(("PyThread_down_sema(%lx) return\n", (long) sema));
  397.     return success;
  398. }
  399.  
  400. void PyThread_up_sema _P1(sema, PyThread_type_sema sema)
  401. {
  402.     int status, error = 0;
  403.     struct semaphore *thesema = (struct semaphore *) sema;
  404.  
  405.     dprintf(("PyThread_up_sema(%lx)\n", (long) sema));
  406.     status = pthread_mutex_lock(&thesema->mutex);
  407.     CHECK_STATUS("pthread_mutex_lock");
  408.     thesema->value++;
  409.     status = pthread_cond_signal(&thesema->cond);
  410.     CHECK_STATUS("pthread_cond_signal");
  411.     status = pthread_mutex_unlock(&thesema->mutex);
  412.     CHECK_STATUS("pthread_mutex_unlock");
  413. }
  414.